package com.tarena.csmall.front.web.repository;

import cn.tedu.mall.pojo.front.entity.FrontCategoryEntity;
import com.alibaba.fastjson.JSON;
import com.tarena.csmall.front.web.mapper.CategoryMapper;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Repository;

@Repository
public class CategoryRespositoryImpl implements CategoryRepository{
    //持久层增删查改
    @Autowired
    private CategoryMapper categoryMapper;
    //缓存层增删查改
    //当前这个对象的序列化方式 采用的是JDK的序列化方式 serializable 默认序列化在redis存储的数据看不懂
    //StringRedisTemplate 序列化方式 是String 可以看到字符串的,如果是对象可以手动json转换
    @Autowired
    private StringRedisTemplate redisTemplate;
    //要求所有的key和value的类型必须实现接口Serializable接口
//    @Autowired
//    private RedisTemplate redisTemplate1;
    @Override public List<FrontCategoryEntity> getCategoryChildren(long parentId) {
        //在数据层的实现,来考虑 数据的获取来源
        //定义一个缓存的key值,设计key要和业务绑定
        String catsKey="cats:tree:"+parentId;
        //判断缓存是否命中 true 命中 false 没有命中
        //底层redis命令:exists cats:tree:parentId
        Boolean hasKey = redisTemplate.hasKey(catsKey);
        //redis有5种基本的数据类型 在spring整合redis的spring-data中,并没有用一个对象
        //来实现多种数据类型的操作,而是分开封装的
        //String类型 拿到ValueOperation
        //Hash类型 拿到HashOperation
        //List类型 拿到ListOperation
        ListOperations<String, String> opsForList = redisTemplate.opsForList();
        if (hasKey){
            //命中缓存
            //读取数据和反序列化的过程 lrang cats:tree:parentId 0 -1
            List<String> cacheCategories = opsForList.range(catsKey, 0, -1);//lrange cats:tree:parentId 0 -1
            //将json字符串转换成java对象
            List<FrontCategoryEntity> categories=new ArrayList<>();
            for (String catJson : cacheCategories) {
                FrontCategoryEntity category = JSON.toJavaObject(JSON.parseObject(catJson), FrontCategoryEntity.class);
                categories.add(category);
            }
            return categories;
        }else{
            //没命中 读数据库 更新缓存 返回数据
            List<FrontCategoryEntity> categories = categoryMapper.selectCategoriesByParentId(parentId);
            //查到的数据可能是空,如果是空,返回不做缓存处理
            if (categories==null||categories.size()==0){
                return null;
            }
            //放到redis缓存中,使用redis的list结构来存储
            List<String> cacheCategories=new ArrayList<>();
            for (FrontCategoryEntity category : categories) {
                String catJson= JSON.toJSONString(category);
                cacheCategories.add(catJson);
                //lpush cats:tree:parentId catJson
                //opsForList.leftPush(catsKey,catJson);
            }
            //存储到redis lpush cats:tree:parentId cacheCategories所有元素
            opsForList.leftPushAll(catsKey,cacheCategories);
            return categories;
        }
    }
}
